﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Activities;
using InspectionPageFlow;
using System.Runtime.Persistence;
using System.Activities.DurableInstancing;
using System.Configuration;
using InspectionVehicule.Pages;
using System.Threading;

namespace InspectionVehicule.WorkflowHost
{
    public class InspectionWorkflowHost : IInspectionWorkflowHost
    {
        PageNavigationExtension extension = new PageNavigationExtension();
        public Guid WorkflowId { get; set; }
        public Object Donnees { get; set; }

        public string DemarrerInspection(string nomMecanicien)
        {
            Dictionary<string, object> parametres = new Dictionary<string, object>();
            parametres.Add("NomMecanicienArg", nomMecanicien);
            WorkflowApplication workflow = GetWorkflow(parametres);
            
            WorkflowId = workflow.Id;
            
            workflow.Run();
            
            return extension.UrlPage;
        }

        public string RouterPage(object state, string etapeEnCours, NavigationAction action)
        {
            WorkflowApplication workflow = GetWorkflow(null);
            
            // Charge le workflow de la persistance
            workflow.Load(WorkflowId);
            extension.Donnees = state;

            if (String.IsNullOrEmpty(etapeEnCours))
                etapeEnCours = ObtenirEtapeEnCours(workflow);

            workflow.ResumeBookmark(etapeEnCours, action);
            
            Donnees = extension.Donnees;
            return extension.UrlPage;
        }

        private string ObtenirEtapeEnCours(WorkflowApplication workflow)
        {
            return workflow.GetBookmarks().First().BookmarkName;
        }

        private WorkflowApplication GetWorkflow(IDictionary<string, object> parametres)
        {
            WorkflowApplication workflow = null;
            
            if (parametres == null)
                workflow = new WorkflowApplication(new InspectionPageFlow.PageFlow());
            else
                workflow = new WorkflowApplication(new InspectionPageFlow.PageFlow(), parametres);

            workflow.InstanceStore = GetInstanceStore();

            // Indique au workflow qu'il doit être persisté et déchargé de la mémoire lorsqu'il est en attente (idle)
            workflow.PersistableIdle = (e) => { return PersistableIdleAction.Unload; };

            // Extension qui permet au workflow de contrôler la navigation.
            // Les activités ont accès aux extensions via le context d'exécution.
            workflow.Extensions.Add(this.extension);

            workflow.SynchronizationContext = SynchronizationContext.Current;            

            return workflow;
        }

        private static InstanceStore GetInstanceStore()
        {
            InstanceStore instanceStore = new SqlWorkflowInstanceStore(
                ConfigurationManager.ConnectionStrings["SqlWorkflowInstanceStore"].ConnectionString);

            // TODO Comprendre ce que c'est deux lignes de code font dans la vie.
            InstanceView view = instanceStore.Execute(instanceStore.CreateInstanceHandle(), new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(30));
            instanceStore.DefaultInstanceOwner = view.InstanceOwner;
            
            return instanceStore;
        }

    }
}